/***
 * Modify Histroy
 * NO.01 2014/12/18  如果玻璃ID重复,用玻璃ID+内部订单ID 生成一笔新的记录,fab_sn(实际玻璃)用原玻璃ID记录,便于后续追溯
 */
package com.service;

import static com.def.GenericDef.BANK_OUT;
import static com.def.GenericDef.EMPTY_CARRIER;
import static com.def.GenericDef.EVT_CANCEL_UNPACK;
import static com.def.GenericDef.EVT_STB_INPR;
import static com.def.GenericDef.EVT_WIP_RETAIN;
import static com.def.GenericDef.EXIST_CARRIER;
import static com.def.GenericDef.E_BIS_MDL_DEF;
import static com.def.GenericDef.E_BIS_PATH;
import static com.def.GenericDef.E_BIS_TOOL_GR;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_RET_BOX;
import static com.def.GenericDef.E_RET_PRD_IN;
import static com.def.GenericDef.E_RET_PRD_INFO;
import static com.def.GenericDef.E_RET_WO;
import static com.def.GenericDef.E_XPUNPACK_BOX_CNT_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_BOX_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_BOX_IS_FULL;
import static com.def.GenericDef.E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_INVALID_BOX_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_BOX_STATUS;
import static com.def.GenericDef.E_XPUNPACK_INVALID_CUS_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_INPUT;
import static com.def.GenericDef.E_XPUNPACK_INVALID_PRD_ID;
import static com.def.GenericDef.E_XPUNPACK_INVALID_WO_COUNT;
import static com.def.GenericDef.E_XPUNPACK_INVALID_WO_STATUS;
import static com.def.GenericDef.E_XPUNPACK_MTRL_BOX_ALREADY_EMPT;
import static com.def.GenericDef.E_XPUNPACK_MTRL_BOX_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_PRD_INFO_EXIST;
import static com.def.GenericDef.E_XPUNPACK_PRD_IN_NOT_ENOUGH;
import static com.def.GenericDef.E_XPUNPACK_REAL_EMPT_FLG_INVALIED;
import static com.def.GenericDef.E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST;
import static com.def.GenericDef.PATH_IS_FINISH;
import static com.def.GenericDef.PRD_TYPE_SHEET;
import static com.def.GenericDef.PROC_EMPTY;
import static com.def.GenericDef.PROC_IN_PROCESS;
import static com.def.GenericDef.PROC_RELS;
import static com.def.GenericDef.PROC_WAIT;
import static com.def.GenericDef.PROC_WFRL;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.SHT_CR_PROC_ID_MIX;
import static com.def.GenericDef.SHT_MDL_CATE_MIX;
import static com.def.GenericDef.SHT_MDL_ID_MIX;
import static com.def.GenericDef.SHT_MDL_TYPE_MIX;
import static com.def.GenericDef.SHT_NX_PROC_ID_MIX;
import static com.def.GenericDef.SHT_NX_TOOLG_MIX;
import static com.def.GenericDef.SHT_OPE_ID_MIX;
import static com.def.GenericDef.SHT_OPE_NO_MIX;
import static com.def.GenericDef.SHT_OPE_VER_MIX;
import static com.def.GenericDef.SHT_PATH_ID_MIX;
import static com.def.GenericDef.SHT_PATH_VER_MIX;
import static com.def.GenericDef.SHT_WO_ID_MIX;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPUNPACK;
import static com.def.GenericDef.WIP_REATIN;
import static com.def.GenericDef.WO_STATUS_CLOS;
import static com.def.GenericDef._NO;
import static com.def.GenericDef._NO1_50;
import static com.def.GenericDef._NORMAL;
import static com.def.GenericDef._OK;
import static com.def.GenericDef._SPACE;
import static com.def.GenericDef._YES;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisDataDao;
import com.dao.IBisMdlDefDao;
import com.dao.IBisOpeDao;
import com.dao.IBisPathDao;
import com.dao.IBisPathiDao;
import com.dao.IBisToolDao;
import com.dao.IBisToolGrDao;
import com.dao.IRetBoxDao;
import com.dao.IRetCusPrdInDao;
import com.dao.IRetCusPrdIndtDao;
import com.dao.IRetPrdGrdInfoDao;
import com.dao.IRetPrdInDao;
import com.dao.IRetPrdIndtDao;
import com.dao.IRetPrdInfoDao;
import com.dao.IRetPrdJgeDao;
import com.dao.IRetPrdLotDao;
import com.dao.IRetTmCusPrdInDao;
import com.dao.IRetTmCusPrdIndtDao;
import com.dao.IRetWODao;
import com.icim.service.ICIMBaseService;
import com.model.Bis_data;
import com.model.Bis_mdl_def;
import com.model.Bis_ope;
import com.model.Bis_opeId;
import com.model.Bis_path;
import com.model.Bis_pathId;
import com.model.Bis_pathi;
import com.model.Bis_pathiId;
import com.model.Bis_tool_gr;
import com.model.Bis_tool_grId;
import com.model.Ret_box;
import com.model.Ret_cus_prd_in;
import com.model.Ret_cus_prd_indt;
import com.model.Ret_prd_grd_info;
import com.model.Ret_prd_in;
import com.model.Ret_prd_inId;
import com.model.Ret_prd_indt;
import com.model.Ret_prd_indtId;
import com.model.Ret_prd_info;
import com.model.Ret_prd_lot;
import com.model.Ret_tm_cus_prd_in;
import com.model.Ret_tm_cus_prd_indt;
import com.model.Ret_wo;
import com.rtnBean.NotFoundRtnBeen;
import com.rtnBean.RouteObj;
import com.rtnBean.SimpleRtnBeen;
import com.tx.Xpunpack.XpunpackI;
import com.tx.Xpunpack.XpunpackO;
import com.util.GUIDGenerator;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XpunpackService")
public class XpunpackService extends ICIMBaseService {
    private static final int RETURN_SHT_ID_BY_WO = 9;
    private Logger logger = Logger.getLogger(XpunpackService.class);
    private static String TX_NAME = T_XPUNPACK;

    private XpunpackI inTrx;
    private XpunpackO outTrx;
    private MqOpe mqOpe;

    private String gszMsgBuf = "";
    private Timestamp gEvtTimestamp;
    private Double gEvtTimeD;
    private String gEvtSeqID;
    /**
     * 判断是否是最后一站
     */
    private long last_ope = 0000000;
    @Autowired
    private IBisDataDao bisDataDao;
    @Autowired
    private IBisToolDao bisToolDao;
    @Autowired
    private IRetPrdInDao retPrdInDao;
    @Autowired
    private IRetPrdIndtDao retPrdIndtDao;
    @Autowired
    private IRetBoxDao retBoxDao;
    @Autowired
    private IRetPrdInfoDao retPrdInfoDao;
    @Autowired
    private IRetWODao retWoDao;
    @Autowired
    private IBisMdlDefDao bisMdlDefDao;
    @Autowired
    private IBisOpeDao bisOpeDao;
    @Autowired
    private IBisPathDao bisPathDao;
    @Autowired
    private IBisPathiDao bisPathiDao;
    @Autowired
    private IRetPrdJgeDao retPrdJgeDao;
    @Autowired
    private IBisToolGrDao bisToolGrDao;
    @Autowired
    private IRetPrdGrdInfoDao retPrdGrdInfoDao;
    @Autowired
    private IRetCusPrdIndtDao retCusPrdIndtDao;
    @Autowired
    private IRetCusPrdInDao retCusPrdInDao;
    @Autowired
    private IRetPrdLotDao retPrdLotDao;
    @Autowired
    private IRetTmCusPrdInDao retTmCusPrdInDao;
    @Autowired
    private IRetTmCusPrdIndtDao retTmCusPrdIndtDao;


    public String subMainProc(String strInMsg) {
        Session session = retPrdInfoDao.getCrSession();

        long rtnCode = _NORMAL;
        String outMsg = null;
        gszMsgBuf = "";
        gEvtTimestamp = Util.getCurrentTimestamp();
        gEvtTimeD = Util.getDoubleTime();
        gEvtSeqID = GUIDGenerator.javaGUID();

        inTrx = new XpunpackI();
        outTrx = new XpunpackO();
        outTrx.setTrx_id(TX_NAME);
        outTrx.setType_id(TRX_OUT);
        outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
        mqOpe = new MqOpe();

        try {
            inTrx = (XpunpackI) mqOpe.inStr2Obj(strInMsg, inTrx);
            logger.info("InTrx is " + strInMsg);

            rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
            if (rtnCode != _NORMAL) {
                TransactionAspectSupport.currentTransactionStatus()
                        .setRollbackOnly();
                outTrx.setRtn_code(String.valueOf(rtnCode));
                outTrx.setRtn_mesg(gszMsgBuf);
            } else {
                outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
                outTrx.setRtn_mesg(RETURN_MESG_OK);
                session.flush();
            }
        } catch (Exception ex) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
            outTrx.setRtn_mesg(ex.toString());
            outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
            logger.error(Util.stackTraceToString(ex));
        } finally {
            outMsg = mqOpe.obj2Str(outTrx);
            logger.info(outMsg);
        }
        return outMsg;
    }

    private long subMainProc2(char actionType) {
        long lRc = _NORMAL;
        switch (actionType) {
            case 'U': {
                lRc = unpackOpe();
                break;
            }
            case 'C': {
                lRc = cancelUnpackOpe();
                break;
            }
            case 'M': {
                lRc = getMtrlBoxInfo();
                break;
            }
            case 'X': {
                lRc = checkXmtmPrdIndtProc();
                break;
            }
            default: {
                gszMsgBuf = "Invalide type input: [" + actionType + "]";
                return E_XPUNPACK_INVALID_INPUT;
            }
        }

        return lRc;
    }

    /**
     * 查询来料箱号信息
     *
     * @return
     */
    private long getMtrlBoxInfo() {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Ret_prd_in ret_prd_in = new Ret_prd_in();

        rtnBeen = retPrdInDao.getRetPrdInByWoAndBox(inTrx.getWo_id(),
                inTrx.getMtrl_box_id());
        if (E_RET_PRD_IN + E_READ_NOT_FOUND == rtnBeen.getlRc()) {
            gszMsgBuf = "内部订单[" + inTrx.getWo_id() + "]中没有箱子["
                    + inTrx.getMtrl_box_id() + "]!";
            return rtnBeen.getlRc();
        } else {
            ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
            outTrx.setRet_prd_in(ret_prd_in);
        }

        return _NORMAL;
    }

    /**
     * Unpack by panel
     *
     * @return
     */
    private long unpackOpe() {
        long lRc;
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Ret_wo ret_wo = new Ret_wo();
        Bis_mdl_def bis_mdl_def = new Bis_mdl_def();
        Ret_box ret_box = new Ret_box();
        Ret_prd_in ret_prd_in = new Ret_prd_in();
        Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
        Ret_prd_info ret_prd_info = new Ret_prd_info();

        Bis_path bis_path = new Bis_path();
        Bis_ope bis_ope = new Bis_ope();
        Bis_path nx_bis_path = new Bis_path();
        Bis_ope nx_bis_ope = new Bis_ope();
        Ret_cus_prd_indt ret_cus_prd_indt = new Ret_cus_prd_indt();
        Ret_cus_prd_in ret_cus_prd_in = new Ret_cus_prd_in();
        //定义产品ID
        String prd_seq_id = "";

        //NO.01 定义fab_sn
        String fab_sn = "";

        // Check wo
        rtnBeen = woCheck(inTrx.getWo_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_wo = (Ret_wo) rtnBeen.getObj();
        }

        // Check mdl info
        rtnBeen = bisMdlDefCheck(ret_wo);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            bis_mdl_def = (Bis_mdl_def) rtnBeen.getObj();
        }

        lRc = getMtrlBoxInfo();
        if (lRc != _NORMAL) {
            return lRc;
        }

        // Check mtrl box / prd_in
        rtnBeen = retMtrlBoxCheck(ret_wo.getWo_id(), inTrx.getMtrl_box_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
        }

        // Check box
        rtnBeen = retBoxCheck(inTrx.getBox_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_box = (Ret_box) rtnBeen.getObj();
        }

        /**
         * 传入的产品ID为空时，自动生成ID（规则：玻璃ID=客户ID+内部订单号+0001流水号）
         * 不为空则检查ID是否重复
         */
        if (Util.isSpaceCheck(inTrx.getPrd_seq_id())) {
            // Check prd_info
            prd_seq_id = creatPrd(ret_wo);
            fab_sn = prd_seq_id;
            logger.info(fab_sn);
        } else {
//			if(ret_wo.getCus_id_fk().equals("088")){
//				prd_seq_id = inTrx.getPrd_seq_id().substring(0, inTrx.getPrd_seq_id().length()-1);
//			}else{
//				prd_seq_id = inTrx.getPrd_seq_id();
//			}
            prd_seq_id = inTrx.getPrd_seq_id();
            fab_sn = prd_seq_id;

            // Check prd_info
            rtnBeen = retPrdInfoCheck(prd_seq_id, ret_wo.getCus_id_fk());
            if (rtnBeen.getlRc() == RETURN_SHT_ID_BY_WO) {
                //NO.02 如果玻璃ID重复,用玻璃ID+工单组合生成新的玻璃ID
                prd_seq_id = (String) rtnBeen.getObj();
            } else if (rtnBeen.getlRc() != _NORMAL) {
                return rtnBeen.getlRc();
            }
        }

        // Check prd_indt
        rtnBeen = retPrdIndtCheck(prd_seq_id);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Check ret_cus_prd_in
        rtnBeen = retCusPrdInCheck(ret_wo);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_cus_prd_in = (Ret_cus_prd_in) rtnBeen.getObj();
        }

        // Check ret_cus_prd_indt
        rtnBeen = retCusPrdIndtCheck(prd_seq_id, ret_wo);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_cus_prd_indt = (Ret_cus_prd_indt) rtnBeen.getObj();
        }

        // Get path info
        // RouteObj
        rtnBeen = getPathInfoByWo(ret_wo, bis_mdl_def);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            bis_path = ((RouteObj) rtnBeen.getObj()).getPath();
            bis_ope = ((RouteObj) rtnBeen.getObj()).getOpe();
        }

        // Get next path info
        // RouteObj
        rtnBeen = getNextPathInfo(bis_path, bis_ope);
        if (rtnBeen.getlRc() != _NORMAL) {
            if (PATH_IS_FINISH == rtnBeen.getlRc()) {
                last_ope = PATH_IS_FINISH;
            } else {
                gszMsgBuf = ((RouteObj) rtnBeen.getObj()).getGszMsgBuf();
                return rtnBeen.getlRc();
            }
        } else {
            nx_bis_path = ((RouteObj) rtnBeen.getObj()).getPath();
            nx_bis_ope = ((RouteObj) rtnBeen.getObj()).getOpe();
        }

        // Check inTrx's tool_id => ope vs wo's start ope
        rtnBeen = chkInputToolVsWoIndo(bis_ope);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Add prd_indt
        rtnBeen = addPrdIndtForUnpack(ret_prd_in, prd_seq_id, ret_cus_prd_indt);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_indt = (Ret_prd_indt) rtnBeen.getObj();
        }

        // Add prd_info
        rtnBeen = addPrdInfoForUnpack(ret_box, ret_wo, bis_mdl_def, bis_path,
                bis_ope, nx_bis_path, nx_bis_ope, ret_prd_in,
                ret_prd_indt.getMtrl_slot_no(), prd_seq_id, fab_sn,
                ret_cus_prd_in);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
        }

        //add prd_grd_info
        rtnBeen = addPrdGrdInfoForUnpack(ret_wo, prd_seq_id);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Check mix
        rtnBeen = checkRetPrdInfoMix(ret_prd_info, ret_box, ret_wo);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Update box
        rtnBeen = updateBoxInfo(ret_box, ret_wo, bis_mdl_def,
                ret_cus_prd_in);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_box = (Ret_box) rtnBeen.getObj();
        }

        // Update mtrl box / prd_in
        rtnBeen = updateMtrlBoxInfo(ret_prd_in);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
        }

        // Update wo info
        rtnBeen = updateWoInfo(ret_wo);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_wo = (Ret_wo) rtnBeen.getObj();
        }

        // Set outTrx
        setOutTrx(ret_prd_indt, ret_prd_info, ret_box, ret_wo, ret_prd_in);

        return _NORMAL;
    }

    /**
     * 检查用户选择的机台是否和工单绑定的起始站点匹配
     *
     * @param ret_wo
     * @param bis_ope
     * @return SimpleRtnBeen{bis_tool_gr}
     */
    private SimpleRtnBeen chkInputToolVsWoIndo(Bis_ope bis_ope) {
        String toolG = bis_ope.getToolg_id();
        Bis_tool_gr bis_tool_gr = new Bis_tool_gr();
        Bis_tool_grId bis_tool_grId = new Bis_tool_grId();
        bis_tool_grId.setTool_id_fk(inTrx.getTool_id());
        bis_tool_grId.setToolg_id(toolG);
        bis_tool_gr = bisToolGrDao.get(bis_tool_grId);
        if (null == bis_tool_gr) {
            gszMsgBuf = new NotFoundRtnBeen(bis_tool_grId.toString(),
                    Bis_tool_gr.class).toString();
            return new SimpleRtnBeen(E_BIS_TOOL_GR + E_READ_NOT_FOUND);
        }

        return new SimpleRtnBeen(bis_tool_gr);
    }

    /**
     * Check wo info for unpack panel
     *
     * @return
     */
    private SimpleRtnBeen woCheck(String wo_id) {
        Ret_wo ret_wo = new Ret_wo();

        // Check wo stutas and count
        ret_wo = retWoDao.getWithLock(wo_id, LockMode.UPGRADE);
        if (null == ret_wo) {
            gszMsgBuf = "内部订单 [" + wo_id + "] 不存在!";
            return new SimpleRtnBeen(E_RET_WO + E_READ_NOT_FOUND);
        } else {
            if (WO_STATUS_CLOS.equals(ret_wo.getWo_stat())) {
                gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "] 已经关闭!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_WO_STATUS);
            }
            if (ret_wo.getRl_prd_qty() >= ret_wo.getPln_prd_qty()) {
                gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "] 没有足够的数量!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_WO_COUNT);
            }
            if (ret_wo.getCus_id_fk() == null) {
                gszMsgBuf = "内部订单 [" + ret_wo.getWo_id() + "]的客户代码为null!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_CUS_ID);
            }
        }

        return new SimpleRtnBeen(ret_wo);
    }

    /**
     * Get current wo's mdl info
     *
     * @param ret_wo
     * @return
     */
    private SimpleRtnBeen bisMdlDefCheck(Ret_wo ret_wo) {
        Bis_mdl_def bis_mdl_def = new Bis_mdl_def();
        // Check wo mdl
        bis_mdl_def = bisMdlDefDao.get(ret_wo.getMdl_id_fk());
        if (null == bis_mdl_def) {
            gszMsgBuf = " Not found record [" + ret_wo.getMdl_id_fk()
                    + "] in ["
                    + Bis_mdl_def.class.getSimpleName().toUpperCase() + "]!";
            return new SimpleRtnBeen(E_BIS_MDL_DEF + E_READ_NOT_FOUND);
        }
        return new SimpleRtnBeen(bis_mdl_def);
    }

    /**
     * Check box info
     *
     * @return
     */
    private SimpleRtnBeen retBoxCheck(String boxId) {
        Ret_box ret_box = new Ret_box();
        ret_box = retBoxDao.getWithLock(boxId, LockMode.UPGRADE);
        if (null == ret_box) {
            gszMsgBuf = "箱子 [" + boxId + "] 不存在!";
            return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND);
        }

        if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
            gszMsgBuf = "箱子 [" + ret_box.getBox_id() + "] " + "状态是 ["
                    + ret_box.getBox_stat() + "], " + "必须是 " + PROC_EMPTY + "!";
            return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_STATUS);
        }

        if (_YES.equals(ret_box.getReal_emp())) {
            if (0 != ret_box.getPrd_qty()) {
                gszMsgBuf = "Box [" + ret_box.getBox_id()
                        + "] is real empt, prd count is ["
                        + ret_box.getPrd_qty() + "], must be 0!";
                return new SimpleRtnBeen(E_XPUNPACK_BOX_CNT_INVALIED);
            }
        } else if (!_NO.equals(ret_box.getReal_emp())) {
            gszMsgBuf = "Box [" + ret_box.getBox_id() + "]'s real empt flg  ["
                    + ret_box.getReal_emp() + "] invalied!";
            return new SimpleRtnBeen(E_XPUNPACK_REAL_EMPT_FLG_INVALIED);
        }

        if (!_YES.equals(ret_box.getValid_flg())) {
            gszMsgBuf = "Box [" + ret_box.getBox_id() + "] is invalied!";
            return new SimpleRtnBeen(E_XPUNPACK_BOX_INVALIED);
        }
        if (ret_box.getPrd_qty().intValue() >= ret_box.getStd_qty().intValue()) {
            gszMsgBuf = "Box [" + ret_box.getBox_id() + "] is full!";
            return new SimpleRtnBeen(E_XPUNPACK_BOX_IS_FULL);
        }

        return new SimpleRtnBeen(ret_box);
    }

    /**
     * Check mtrl box info
     *
     * @param ret_wo
     * @param boxId
     * @return
     */
    private SimpleRtnBeen retMtrlBoxCheck(String woId, String boxId) {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Ret_prd_in ret_prd_in = new Ret_prd_in();
        Ret_prd_inId ret_prd_inId = new Ret_prd_inId();

        String cus_id = retPrdInDao.getCusIdOfMtrlBox(woId, boxId);
        ret_prd_inId.setCus_id(cus_id);
        ret_prd_inId.setMtrl_box_id(boxId);

        ret_prd_in = retPrdInDao.getWithLock(ret_prd_inId, LockMode.UPGRADE);
        if (null == ret_prd_in) {
            gszMsgBuf = " 箱子[" + boxId + "]在内部订单[" + woId + "] 中不存在！！ ["
                    + Ret_prd_in.class.getSimpleName().toUpperCase() + "]!";
            return new SimpleRtnBeen(E_RET_PRD_IN + E_READ_NOT_FOUND);
        }
        rtnBeen.setObj(ret_prd_in);

        if (PROC_WAIT.equals(ret_prd_in.getPpbox_stat())) {
            gszMsgBuf = "来料箱[" + ret_prd_in.getId().getMtrl_box_id()
                    + "]尚未领料， 请先进行领料操作！";
            return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
        }

        if (PROC_EMPTY.equals(ret_prd_in.getPpbox_stat())) {
            gszMsgBuf = "来料箱[" + ret_prd_in.getId().getMtrl_box_id()
                    + "]已经释放完毕！";
            return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_ALREADY_EMPT);
        }

        if (0 >= ret_prd_in.getPrd_act_qty()) {
            gszMsgBuf = "Mtrl box[" + ret_prd_in.getId().getMtrl_box_id()
                    + "] is not panel to use.";
            return new SimpleRtnBeen(E_XPUNPACK_PRD_IN_NOT_ENOUGH);
        }

        return rtnBeen;
    }

    /**
     * Check prd info
     *
     * @return
     */
    private SimpleRtnBeen retPrdInfoCheck(String prdId, String cusId) {
        Ret_prd_info ret_prd_info = new Ret_prd_info();
        ret_prd_info = retPrdInfoDao.get(prdId);
        if (null != ret_prd_info) {
            if (ret_prd_info.getWo_id_fk().equals(inTrx.getWo_id())) {
                gszMsgBuf = "玻璃重复[" + prdId + "]!";
                return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
            }

            /**
             * 1、已投产品内部订单无信息时，可以继续投产；
             * 2、已投产品内部订单有信息时，已投产品的客户订单已维护SGID，并且预投产品客户订单也维护了SGID，则不允许投产
             * 其他情况允许投产
             */
            Ret_wo ret_wo = retWoDao.getWithLock(ret_prd_info.getWo_id_fk(), LockMode.UPGRADE);
            if (ret_wo != null) {
                List<Bis_data> dataList = new ArrayList<Bis_data>();
                String hql = "FROM Bis_data where data_cate = 'SGID' and ext_1 = '" + ret_wo.getCus_id_fk() + "'";
                dataList = bisDataDao.find(hql);
                if (!dataList.isEmpty()) {
                    hql = "FROM Bis_data where data_cate = 'SGID' and ext_1 = '" + cusId + "'";
                    dataList = bisDataDao.find(hql);
                    if (!dataList.isEmpty()) {
                        gszMsgBuf = "玻璃重复[" + prdId + "]!";
                        return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
                    }
                }
            }

            prdId = buildPrdIdByWo(prdId, inTrx.getWo_id());
            ret_prd_info = retPrdInfoDao.get(prdId + "");
            if (null != ret_prd_info) {
                gszMsgBuf = "玻璃重复[" + prdId + "]!";
                return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
            }
            return new SimpleRtnBeen(RETURN_SHT_ID_BY_WO, new String(prdId), "根据工单ID组合生成");
        }

        return new SimpleRtnBeen(_NORMAL, prdId + "_" + inTrx.getWo_id());
    }

    private String buildPrdIdByWo(String prdId, String woId) {
        return prdId + "_" + woId;
    }

    /**
     * Check prd indt
     *
     * @return
     */
    private SimpleRtnBeen retPrdIndtCheck(String prdId) {
        Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
        Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();
        ret_prd_indtId.setVdr_prd_seq_id(prdId);
        ret_prd_indtId.setAct_typ(_NO);
        ret_prd_indt = retPrdIndtDao.get(ret_prd_indtId);
        if (null != ret_prd_indt) {
            gszMsgBuf = "[" + prdId + "] exist in ["
                    + Ret_prd_indt.class.getSimpleName().toUpperCase() + "]!";
            return new SimpleRtnBeen(E_XPUNPACK_PRD_INFO_EXIST);
        }

        return new SimpleRtnBeen(ret_prd_indt);
    }

    /**
     * Get current path ope info
     *
     * @param ret_wo
     * @return SimpleRtnBeen(RouteObj)
     */
    private SimpleRtnBeen getPathInfoByWo(Ret_wo ret_wo, Bis_mdl_def bis_mdl_def) {
        Bis_path bis_path = new Bis_path();
        Bis_pathId bis_pathId = new Bis_pathId();
        Bis_ope bis_ope = new Bis_ope();
        Bis_opeId bis_opeId = new Bis_opeId();
        RouteObj routeObj = new RouteObj();

        bis_pathId.setPath_id_fk(ret_wo.getPath_id_fk());
        bis_pathId.setPath_ver_fk(ret_wo.getPath_ver_fk());
        bis_pathId.setCr_ope_no(ret_wo.getStr_ope_no());
        bis_path = bisPathDao.get(bis_pathId);
        if (null == bis_path) {
            gszMsgBuf = " 找不到记录 [" + bis_pathId.toString() + "] in ["
                    + Bis_path.class.getSimpleName().toUpperCase() + "]!";
            return new SimpleRtnBeen(E_BIS_PATH + E_READ_NOT_FOUND);
        }

        bis_opeId.setOpe_id(bis_path.getCr_ope_id_fk());
        bis_opeId.setOpe_ver(bis_path.getCr_ope_ver_fk());
        bis_ope = bisOpeDao.get(bis_opeId);
        if (null == bis_ope) {
            gszMsgBuf = " 找不到记录 [" + bis_opeId.toString() + "] in ["
                    + Bis_ope.class.getSimpleName().toUpperCase() + "]!";
            return new SimpleRtnBeen(E_BIS_PATH + E_READ_NOT_FOUND);
        }

        routeObj.setPath(bis_path);
        routeObj.setOpe(bis_ope);
        routeObj.setLRc(_NORMAL);

        return new SimpleRtnBeen(routeObj);
    }

    /**
     * Get next path info
     *
     * @param bis_path
     * @param bis_ope
     * @return
     */
    private SimpleRtnBeen getNextPathInfo(Bis_path bis_path, Bis_ope bis_ope) {
        RouteObj routeObjRtn = new RouteObj();
        routeObjRtn = bisPathDao.getNxPath(bis_path);
        return new SimpleRtnBeen(routeObjRtn.getLRc(), routeObjRtn);
    }

    /**
     * Add prd_indt
     *
     * @return RouteObj
     */
    private SimpleRtnBeen addPrdIndtForUnpack(Ret_prd_in ret_prd_in, String prd_seq_id,
                                              Ret_cus_prd_indt ret_cus_prd_indt) {
        int slot_no_box = retBoxDao.get(inTrx.getBox_id()).getStd_qty();
        Ret_prd_indt ret_prd_indt = new Ret_prd_indt();
        Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();

        ret_prd_indtId.setVdr_prd_seq_id(prd_seq_id);
        ret_prd_indtId.setAct_typ(_NO);
        ret_prd_indt.setId(ret_prd_indtId);

        ret_prd_indt.setPrd_stat(PROC_RELS);
        ret_prd_indt.setMtrl_box_id_fk(ret_prd_in.getId().getMtrl_box_id());
        /**
         * ret_cus_prd_indt 为null，代表非客户，slot_no需按规则生成；
         * 非null时，代表为客户订单，slot_no按照ret_cus_prd_indt中的mtrl_slot_no获取
         */
//		if(ret_cus_prd_indt != null){
//			ret_prd_indt.setMtrl_slot_no(ret_cus_prd_indt.getMtrl_slot_no());
//		}else{
        if (Util.isSpaceCheck(inTrx.getSlot_no())) {
        /*		String sql = "SELECT MAX(CAST(SLOT_NO AS SIGNED)) FROM Ret_prd_info WHERE box_id_fk='"+inTrx.getBox_id()+"'";
				List list = retPrdInfoDao.findBySQL(sql);
				String max_slot = list.get(0) == null ? 1+"" : ((BigInteger)list.get(0)).intValue()+1+""; */
	/*			String hql = "FROM Ret_prd_info WHERE　box_id_fk=?";
				list = retPrdInfoDao.list(hql, inTrx.getBox_id());*/
            String sql = "SELECT SLOT_NO FROM Ret_prd_info WHERE box_id_fk='" + inTrx.getBox_id() + "' ORDER BY  CAST(SLOT_NO AS SIGNED)";
            List list = retPrdInfoDao.findBySQL(sql);
            List<Integer> slots = new ArrayList<Integer>();
            for (int i = 0; i < list.size(); i++) {
                slots.add(Integer.parseInt((String) list.get(i)));
            }
            int tempSlot = 0;
            for (int i = 1; ; i++) {
                if (!slots.contains(i)) {
                    tempSlot = i;
                    break;
                }
            }
            if (tempSlot > slot_no_box) {
                gszMsgBuf = "箱子[" + inTrx.getBox_id() + "]已满";
                return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
            }
            ret_prd_indt.setMtrl_slot_no(tempSlot + "");
        } else {
            int slot_no_inTx = Integer.valueOf(inTrx.getSlot_no());
            if (retPrdInfoDao.hasUserInputSlotInBox(inTrx.getBox_id(),
                    inTrx.getSlot_no())) {
                gszMsgBuf = "子格位[" + inTrx.getSlot_no() + "]在箱子["
                        + inTrx.getBox_id() + "]中已经存在！";
                return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
            } else if (slot_no_inTx > slot_no_box) {
                gszMsgBuf = "输入的子格位为[" + inTrx.getSlot_no() + "]，而箱子["
                        + inTrx.getBox_id() + "]产品最大子格位为["
                        + slot_no_box + "]！";
                return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
            } else {
                ret_prd_indt.setMtrl_slot_no(inTrx.getSlot_no());
            }
//				else if (slot_no_inTx > slot_no_prdIn) {
//					gszMsgBuf = "输入的子格位为[" + inTrx.getSlot_no() + "]，而来料箱["
//							+ ret_prd_in.getId().getMtrl_box_id() + "]产品最大子格位为["
//							+ ret_prd_in.getBox_std_qty() + "]！";
//					return new SimpleRtnBeen(E_XPUNPACK_SLOT_NO_IN_MTRL_EXIST);
//				} 

        }
//		}
        ret_prd_indt.setWo_id_fk(inTrx.getWo_id());
        ret_prd_indt.setEvt_timestamp(gEvtTimestamp);
        ret_prd_indt.setEvt_usr(inTrx.getEvt_usr());
        retPrdIndtDao.save(ret_prd_indt);

        return new SimpleRtnBeen(ret_prd_indt);
    }

    /**
     * Add new prd_info record
     *
     * @param ret_box
     * @param ret_wo
     * @param bis_mdl_def
     * @param bis_path
     * @param bis_ope
     * @param nx_bis_path
     * @param nx_bis_ope
     * @param ret_prd_in
     * @return SimpleRtnBeen
     */
    private SimpleRtnBeen addPrdInfoForUnpack(Ret_box ret_box, Ret_wo ret_wo,
                                              Bis_mdl_def bis_mdl_def, Bis_path bis_path, Bis_ope bis_ope,
                                              Bis_path nx_bis_path, Bis_ope nx_bis_ope, Ret_prd_in ret_prd_in,
                                              String slotNo, String prd_seq_id, String fab_sn,
                                              Ret_cus_prd_in ret_cus_prd_in) {

        Integer pnl_std_pnl = 0;
        Ret_prd_info ret_prd_info = new Ret_prd_info();

        // Set ret_prd_info
        ret_prd_info.setPrd_seq_id(prd_seq_id);
        ret_prd_info.setPrd_stat(PROC_IN_PROCESS);
        ret_prd_info.setPrd_seq_typ(PRD_TYPE_SHEET);
        ret_prd_info.setBox_id_fk(inTrx.getBox_id());
        ret_prd_info.setSlot_no(slotNo);
        ret_prd_info.setMdl_typ_fk(bis_mdl_def.getMdl_typ());
        ret_prd_info.setMdl_cate_fk(ret_wo.getMdl_cate_fk());
        ret_prd_info.setMdl_id_fk(bis_mdl_def.getMdl_id());
        ret_prd_info.setMtrl_box_id_fk(inTrx.getMtrl_box_id());
        ret_prd_info.setMtrl_prod_id_fk(ret_prd_in.getMtrl_prod_id_fk());
        ret_prd_info.setLayot_id_fk(inTrx.getLayot_id());
        ret_prd_info.setX_axis_cnt_fk(Integer.valueOf(inTrx.getX_axis_cnt()));
        ret_prd_info.setY_axis_cnt_fk(Integer.valueOf(inTrx.getY_axis_cnt()));
        /**
         * ret_cus_prd_in 为null，代表非客户；
         * 非null时，代表为客户订单，group id按照ret_cus_prd_in中的cus_group_id
         */
        if (ret_cus_prd_in != null) {
            ret_prd_info.setGroup_id(ret_cus_prd_in.getCus_group_id());
        } else {
            ret_prd_info.setGroup_id("");
        }

        pnl_std_pnl = ret_prd_info.getX_axis_cnt_fk()
                * ret_prd_info.getY_axis_cnt_fk();
        ret_prd_info.setPrd_qty(pnl_std_pnl);
        ret_prd_info.setPrd_std_qty(pnl_std_pnl);
        if (!Util.isSpaceCheck(inTrx.getThickness())) {
            ret_prd_info.setPrd_thickness(Double.valueOf(inTrx.getThickness()));
        } else {
            ret_prd_info.setPrd_thickness(0.0);
        }
        ret_prd_info.setPv_prd_thickness(0.0);

        ret_prd_info.setPrty(ret_wo.getWo_prty());


        Ret_tm_cus_prd_indt retTmCusPrdIndt = retTmCusPrdIndtDao.get(prd_seq_id);
        if (retTmCusPrdIndt != null) {
            ret_prd_info.setPrd_grade(retTmCusPrdIndt.getProductgrade());
            ret_prd_info.setExt_2(retTmCusPrdIndt.getProductgrade());
        } else {
            ret_prd_info.setPrd_grade(_OK);
        }

        ret_prd_info.setPv_prd_grade(_OK);
        // 特定站点过账标识[DATA-PRST-EXT2]
        ret_prd_info.setCus_sn(_NO1_50);
        ret_prd_info.setProc_flg("Y");

        // Path info
        ret_prd_info.setCr_path_id_fk(bis_path.getId().getPath_id_fk());
        ret_prd_info.setCr_path_ver_fk(bis_path.getId().getPath_ver_fk());
        ret_prd_info.setCr_ope_no_fk(bis_path.getId().getCr_ope_no());
        ret_prd_info.setCr_ope_id_fk(bis_path.getCr_ope_id_fk());
        ret_prd_info.setCr_ope_ver_fk(bis_path.getCr_ope_ver_fk());

        ret_prd_info.setCr_proc_id_fk(bis_ope.getProc_id());
        ret_prd_info.setCr_toolg_id_fk(bis_ope.getToolg_id());
        ret_prd_info.setCr_tool_id_fk(inTrx.getTool_id());
        ret_prd_info.setTool_id_fk(inTrx.getTool_id());
        if (last_ope == PATH_IS_FINISH) {
            ret_prd_info.setNx_path_id_fk(bis_path.getId().getPath_id_fk());
            ret_prd_info.setNx_path_ver_fk(bis_path.getId().getPath_ver_fk());
            ret_prd_info.setNx_ope_no_fk(_SPACE);
            ret_prd_info.setNx_ope_id_fk(_SPACE);
            ret_prd_info.setNx_ope_ver_fk(_SPACE);
            ret_prd_info.setNx_proc_id_fk(_SPACE);
            ret_prd_info.setNx_toolg_id_fk(_SPACE);
        } else {
            ret_prd_info.setNx_path_id_fk(nx_bis_path.getId().getPath_id_fk());
            ret_prd_info.setNx_path_ver_fk(nx_bis_path.getId().getPath_ver_fk());
            ret_prd_info.setNx_ope_no_fk(nx_bis_path.getId().getCr_ope_no());
            ret_prd_info.setNx_ope_id_fk(nx_bis_ope.getId().getOpe_id());
            ret_prd_info.setNx_ope_ver_fk(nx_bis_ope.getId().getOpe_ver());
            ret_prd_info.setNx_proc_id_fk(nx_bis_ope.getProc_id());
            ret_prd_info.setNx_toolg_id_fk(nx_bis_ope.getToolg_id());
        }

        // Time info
        ret_prd_info.setAct_stb_timestamp(gEvtTimestamp);
        ret_prd_info.setFst_logon_timestamp(gEvtTimestamp);

        // rubbing_time
        ret_prd_info.setT_rubbing_time(0);
        ret_prd_info.setC_rubbing_time(0);

        // Event info
        ret_prd_info.setEvt_dept("");
        ret_prd_info.setEvt_cate(EVT_STB_INPR);
        ret_prd_info.setEvt_usr(inTrx.getEvt_usr());
        ret_prd_info.setEvt_timestamp(gEvtTimestamp);
        ret_prd_info.setEvt_time_d(gEvtTimeD);
        ret_prd_info.setEvt_seq_id(gEvtSeqID);

        ret_prd_info.setWo_id_fk(inTrx.getWo_id());
        ret_prd_info.setSo_id_fk(ret_wo.getSo_id());

        ret_prd_info.setDest_shop(ret_wo.getDest_shop());
        ret_prd_info.setQrs_ovr_flg(_NO);
        ret_prd_info.setBnk_flg(BANK_OUT);
        ret_prd_info.setPrd_admin_flg("NNNNNNNNNNNNNNNNNNNN");
        ret_prd_info.setFab_sn(fab_sn);//NO.01
        logger.info("set fab sn:" + fab_sn);
        retPrdInfoDao.save(ret_prd_info);
        if (ret_box.getBnk_flg().equals(WIP_REATIN)) {// 在制保留的箱子，转进来的产品均将其BNK_FLG置为3
            gEvtTimestamp = Util.getCurrentTimestamp();
            gEvtTimeD = Util.getDoubleTime();
            gEvtSeqID = GUIDGenerator.javaGUID();
            ret_prd_info.setEvt_timestamp(gEvtTimestamp);
            ret_prd_info.setEvt_time_d(gEvtTimeD);
            ret_prd_info.setEvt_seq_id(gEvtSeqID);
            ret_prd_info.setEvt_cate(EVT_WIP_RETAIN);
            ret_prd_info.setBnk_flg(WIP_REATIN);
            retPrdInfoDao.update(ret_prd_info);
        }
        return new SimpleRtnBeen(ret_prd_info);
    }

    /**
     * Check sht in cur box
     *
     * @return
     */
    private SimpleRtnBeen checkRetPrdInfoMix(Ret_prd_info newPrdInfo,
                                             Ret_box ret_box, Ret_wo ret_wo) {
        List<Ret_prd_info> ret_prd_infoList = new ArrayList<Ret_prd_info>();
        Ret_prd_info last_prd = new Ret_prd_info();

        String sql = "From Ret_prd_info where box_id_fk = '"
                + ret_box.getBox_id() + "' and prd_seq_id <>'"
                + newPrdInfo.getPrd_seq_id() + "'";
        ret_prd_infoList = retPrdInfoDao.find(sql, 0, 1);
        if (!ret_prd_infoList.isEmpty()) {
            last_prd = ret_prd_infoList.get(0);

            // Proc info
            if (!newPrdInfo.getNx_proc_id_fk().equals(
                    last_prd.getNx_proc_id_fk())) {
                gszMsgBuf = "玻璃的下一制程不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getNx_proc_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_proc_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_NX_PROC_ID_MIX);
            }
            if (!newPrdInfo.getCr_proc_id_fk().equals(
                    last_prd.getCr_proc_id_fk())) {
                gszMsgBuf = "玻璃的当前制程不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getCr_proc_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getCr_proc_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_CR_PROC_ID_MIX);
            }

            // MDL info
            if (!newPrdInfo.getMdl_cate_fk().equals(last_prd.getMdl_cate_fk())) {
                gszMsgBuf = "玻璃的产品类型不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getMdl_cate_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getMdl_cate_fk() + "] ";
                return new SimpleRtnBeen(SHT_MDL_CATE_MIX);
            }
            if (!newPrdInfo.getMdl_id_fk().equals(last_prd.getMdl_id_fk())) {
                gszMsgBuf = "玻璃的产品名称不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getMdl_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getMdl_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_MDL_ID_MIX);
            }
            if (!newPrdInfo.getMdl_typ_fk().equals(last_prd.getMdl_typ_fk())) {
                gszMsgBuf = "玻璃的产品尺寸不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getMdl_typ_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getMdl_typ_fk() + "] ";
                return new SimpleRtnBeen(SHT_MDL_TYPE_MIX);
            }

            // Path in
            if (!newPrdInfo.getNx_path_id_fk().equals(
                    last_prd.getNx_path_id_fk())) {
                gszMsgBuf = "玻璃的下一工艺路线不能混！[" + newPrdInfo.getPrd_seq_id()
                        + "][" + newPrdInfo.getNx_path_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_path_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_PATH_ID_MIX);
            }
            if (!newPrdInfo.getNx_path_ver_fk().equals(
                    last_prd.getNx_path_ver_fk())) {
                gszMsgBuf = "玻璃的下一工艺路线版本不能混！ [" + newPrdInfo.getPrd_seq_id()
                        + "][" + newPrdInfo.getNx_path_ver_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_path_ver_fk() + "] ";
                return new SimpleRtnBeen(SHT_PATH_VER_MIX);
            }
            if (!newPrdInfo.getNx_ope_id_fk()
                    .equals(last_prd.getNx_ope_id_fk())) {
                gszMsgBuf = "玻璃的下一站点ID不能混！ [" + newPrdInfo.getPrd_seq_id()
                        + "][" + newPrdInfo.getNx_ope_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_ope_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_OPE_ID_MIX);
            }
            if (!newPrdInfo.getNx_ope_no_fk()
                    .equals(last_prd.getNx_ope_no_fk())) {
                gszMsgBuf = "玻璃的下一站点编号不能混！ [" + newPrdInfo.getPrd_seq_id()
                        + "][" + newPrdInfo.getNx_ope_no_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_ope_no_fk() + "] ";
                return new SimpleRtnBeen(SHT_OPE_NO_MIX);
            }
            if (!newPrdInfo.getNx_ope_ver_fk().equals(
                    last_prd.getNx_ope_ver_fk())) {
                gszMsgBuf = "玻璃的下一站点版本不能混！[" + newPrdInfo.getPrd_seq_id()
                        + "][" + newPrdInfo.getNx_ope_ver_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_ope_ver_fk() + "] ";
                return new SimpleRtnBeen(SHT_OPE_VER_MIX);
            }

            // Tool info
            if (!newPrdInfo.getNx_toolg_id_fk().equals(
                    last_prd.getNx_toolg_id_fk())) {
                gszMsgBuf = "玻璃的设备组不能混！[" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getNx_toolg_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getNx_toolg_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_NX_TOOLG_MIX);
            }

            // WO info
            if (!newPrdInfo.getWo_id_fk().equals(last_prd.getWo_id_fk())) {
                gszMsgBuf = "玻璃的内部订单不能混！ [" + newPrdInfo.getPrd_seq_id() + "]["
                        + newPrdInfo.getWo_id_fk() + "] vs ["
                        + last_prd.getPrd_seq_id() + "]["
                        + last_prd.getWo_id_fk() + "] ";
                return new SimpleRtnBeen(SHT_WO_ID_MIX);
            }

            //GROUP ID,针对客户来料的订单，不同group id(值来自RET_CUS_PRD_IN的CUS_GROUP_ID,即owner id)的产品不能混装
//			if(_YES.equals(ret_wo.getSwh_cnt_flg())||"007".equals(ret_wo.getCus_id_fk())){//客户来料标记
//				if(!newPrdInfo.getGroup_id().equals(last_prd.getGroup_id())){
//					gszMsgBuf = "玻璃的组代码不能混！[" + newPrdInfo.getPrd_seq_id()+ "]["
//						+ newPrdInfo.getGroup_id() + "] vs ["
//						+ last_prd.getPrd_seq_id() + "]["
//						+ last_prd.getGroup_id() + "]";
//					return new SimpleRtnBeen(GROUP_ID_MIX);
//				}
//				if(!newPrdInfo.getPrd_grade().equals(last_prd.getPrd_grade())){
//					gszMsgBuf = "玻璃的等级不能混！[" + newPrdInfo.getPrd_seq_id()+ "]["
//						+ newPrdInfo.getPrd_grade() + "] vs ["
//						+ last_prd.getPrd_seq_id() + "]["
//						+ last_prd.getPrd_grade() + "]";
//					return new SimpleRtnBeen(GROUP_ID_MIX);
//				}
//			}
        }

        return new SimpleRtnBeen(_NORMAL);
    }

    /**
     * Update ret_box info
     *
     * @param ret_box
     * @param ret_wo
     * @param bis_mdl_def
     * @return
     */
    private SimpleRtnBeen updateBoxInfo(Ret_box ret_box, Ret_wo ret_wo,
                                        Bis_mdl_def bis_mdl_def,
                                        Ret_cus_prd_in ret_cus_prd_in) {
        if (EMPTY_CARRIER.equals(ret_box.getReal_emp())) {
            ret_box.setReal_emp(EXIST_CARRIER);
            ret_box.setPrd_qty(1);

            ret_box.setMdl_id_fk(bis_mdl_def.getMdl_id());
            ret_box.setMdl_typ_fk(bis_mdl_def.getMdl_typ());
            ret_box.setMdl_cate_fk(ret_wo.getMdl_cate_fk());
            ret_box.setWo_id_fk(ret_wo.getWo_id());
            ret_box.setPrty(ret_wo.getWo_prty());
            /**
             * ret_cus_prd_in 为null，代表非客户；
             * 非null时，代表为客户订单，group id按照ret_cus_prd_in中的cus_group_id
             */
            if (ret_cus_prd_in != null) {
                ret_box.setGroup_id(ret_cus_prd_in.getCus_group_id());
            } else {
                ret_box.setGroup_id("");
            }
        } else {
            ret_box.setPrd_qty(ret_box.getPrd_qty() + 1);
        }

        retBoxDao.update(ret_box);
        return new SimpleRtnBeen(ret_box);
    }

    /**
     * Update mtrl box/ret_prd_in info
     *
     * @param ret_prd_in
     * @return Ret_prd_in
     */
    private SimpleRtnBeen updateMtrlBoxInfo(Ret_prd_in ret_prd_in) {
        if (PROC_WFRL.equals(ret_prd_in.getPpbox_stat())) {
            ret_prd_in.setEvt_cate(EVT_STB_INPR);
            ret_prd_in.setPrd_proc_qty(1);
            ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_tl_qty() - 1);
            if (0 == ret_prd_in.getPrd_act_qty()) {//fix bug：来料箱只有一个产品ID时，来料箱状态不会变为EMPT
                ret_prd_in.setPpbox_stat(PROC_EMPTY);
            } else {
                ret_prd_in.setPpbox_stat(PROC_RELS);
            }
        } else if (PROC_RELS.equals(ret_prd_in.getPpbox_stat())) {
            ret_prd_in.setPrd_proc_qty(ret_prd_in.getPrd_proc_qty() + 1);
            ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_act_qty() - 1);
            if (0 == ret_prd_in.getPrd_act_qty()) {
                ret_prd_in.setPpbox_stat(PROC_EMPTY);
            }
        } else {
            gszMsgBuf = "Mtrl box's status [" + ret_prd_in.getPpbox_stat()
                    + "] is invalied!";
            return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
        }

        retPrdInDao.update(ret_prd_in);
        return new SimpleRtnBeen(ret_prd_in);
    }

    /**
     * Update wo info
     *
     * @param ret_wo
     * @return Ret_wo
     */
    private SimpleRtnBeen updateWoInfo(Ret_wo ret_wo) {
        if (0 == ret_wo.getRl_prd_qty()) {
            ret_wo.setAct_stb_timestamp(gEvtTimestamp);
        }
        if (null == ret_wo.getAct_stb_timestamp()) {
            ret_wo.setAct_stb_timestamp(gEvtTimestamp);
        }
        ret_wo.setRl_prd_qty(ret_wo.getRl_prd_qty() + 1);
        retWoDao.update(ret_wo);
        return new SimpleRtnBeen(ret_wo);
    }

    private void setOutTrx(Ret_prd_indt ret_prd_indt,
                           Ret_prd_info ret_prd_info, Ret_box ret_box,
                           Ret_wo ret_wo, Ret_prd_in ret_prd_in) {
        outTrx.setMtrl_box_id_fk(ret_prd_indt.getMtrl_box_id_fk());
        outTrx.setSlot_no(ret_prd_info.getSlot_no());
        outTrx.setPrd_seq_id(ret_prd_info.getPrd_seq_id());
        outTrx.setBox_id_fk(ret_prd_info.getBox_id_fk());
        outTrx.setBox_prd_qty(ret_box.getPrd_qty());
        outTrx.setEvt_timestamp(gEvtTimestamp.toString());
        outTrx.setEvt_usr(inTrx.getEvt_usr());
        outTrx.setLayot_id_fk(ret_prd_info.getLayot_id_fk());
        outTrx.setX_axis_cnt_fk(String.valueOf(ret_prd_info.getX_axis_cnt_fk()));
        outTrx.setY_axis_cnt_fk(String.valueOf(ret_prd_info.getY_axis_cnt_fk()));
        outTrx.setFrom_thickness(ret_wo.getFrom_thickness());
        outTrx.setTo_thickness(ret_wo.getTo_thickness());
        outTrx.setPln_prd_qty(ret_wo.getPln_prd_qty());
        outTrx.setRl_prd_qty(ret_wo.getRl_prd_qty());
        outTrx.setRet_prd_in(ret_prd_in);
        outTrx.setPrd_admin_flg(ret_prd_info.getPrd_admin_flg());
        outTrx.setMdl_id_fk(ret_prd_info.getMdl_id_fk());
        outTrx.setCr_tool_id_fk(ret_prd_info.getCr_tool_id_fk());
        outTrx.setCr_path_id_fk(ret_prd_info.getCr_path_id_fk());
        outTrx.setCr_path_ver_fk(ret_prd_info.getCr_path_ver_fk());
        outTrx.setCr_ope_no_fk(ret_prd_info.getCr_ope_no_fk());
        outTrx.setCr_ope_id_fk(ret_prd_info.getCr_ope_id_fk());
        outTrx.setCr_ope_ver_fk(ret_prd_info.getCr_ope_ver_fk());
        outTrx.setCr_proc_id_fk(ret_prd_info.getCr_proc_id_fk());
        outTrx.setWo_id_fk(ret_prd_info.getWo_id_fk());
        outTrx.setFab_sn(ret_prd_info.getFab_sn());
        outTrx.setGroup_id(ret_prd_info.getGroup_id());
        outTrx.setCus_id(ret_wo.getCus_id_fk());
    }

    /**
     * Cancel unpack, update relevant data
     *
     * @return
     */
    private long cancelUnpackOpe() {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Ret_prd_info ret_prd_info = new Ret_prd_info();
        Ret_prd_in ret_prd_in = new Ret_prd_in();
        Ret_wo ret_wo = new Ret_wo();

        // Get & check prd_info
        rtnBeen = checkPrdInfoForCancelUnpack(inTrx.getPrd_seq_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
        }

        rtnBeen = ResetPrdLotInfoForCancelUnpack(inTrx.getPrd_seq_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_info = (Ret_prd_info) rtnBeen.getObj();
        }
        // Reset ret_prd_in
        rtnBeen = resetRetPrdInForCancelUnpack(ret_prd_info.getWo_id_fk(),
                ret_prd_info.getMtrl_box_id_fk());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
        }

        // Delete ret_prd_indt
        rtnBeen = delRetPrdIndtForCancelUnpack(ret_prd_info.getPrd_seq_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Reset ret_box
        rtnBeen = resetRetBoxForCancelUnpack(ret_prd_info.getBox_id_fk(),
                ret_prd_in);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Delete ret_prd_info
        rtnBeen = delRetPrdInfoForCancelUnpack(ret_prd_info);
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Delete ret_grd_info
        rtnBeen = delRetGrdInfoForCancelUnpack();
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Reset ret_wo
        rtnBeen = resetRetWoForCancelUnpack(ret_prd_info.getWo_id_fk());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        } else {
            ret_wo = (Ret_wo) rtnBeen.getObj();
        }

        // Delete defect info
        rtnBeen = delDefForCancelUnpack(ret_prd_info.getPrd_seq_id());
        if (rtnBeen.getlRc() != _NORMAL) {
            return rtnBeen.getlRc();
        }

        // Set outTrx
        setOutTrxForCancelUnpack(inTrx.getPrd_seq_id(), ret_wo, ret_prd_in);

        return _NORMAL;
    }

    /**
     * Get & check prd_info for cancel unpack
     *
     * @param prd_seq_id
     * @return {Ret_prd_info}
     */
    private SimpleRtnBeen checkPrdInfoForCancelUnpack(String prd_seq_id) {
        Ret_prd_info ret_prd_info = new Ret_prd_info();

        ret_prd_info = retPrdInfoDao.get(prd_seq_id);
        if (null == ret_prd_info) {
            gszMsgBuf = new NotFoundRtnBeen(prd_seq_id, Ret_prd_info.class)
                    .toString();
            return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND);
        }

        // Status
        if (!PROC_IN_PROCESS.equals(ret_prd_info.getPrd_stat())) {
            gszMsgBuf = "要删除的玻璃状态必须是[" + PROC_IN_PROCESS + "]，当前玻璃["
                    + prd_seq_id + "]状态为[" + ret_prd_info.getPrd_stat()
                    + "]，禁止取消！";
            return new SimpleRtnBeen(E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED);
        }
        // lot_id
//		if (!Util.isSpaceCheck(ret_prd_info.getLot_id())) {
//			gszMsgBuf = "产品[" + ret_prd_info.getPrd_seq_id() + "]已绑定批次["
//					+ ret_prd_info.getLot_id() + "]，禁止取消！";
//			return new SimpleRtnBeen(E_XPUNPACK_CANCEL_PRD_INFO_STATUS_INVALIED);
//		}


        //取消释放功能,检查玻璃是不是在当前途程的首站点,如果不是则报错
        String path_id = ret_prd_info.getCr_path_id_fk();
        String path_ver = ret_prd_info.getCr_path_ver_fk();

        if (Util.isSpaceCheck(path_id) || Util.isSpaceCheck(path_ver)) {
            gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路为空";
            return new SimpleRtnBeen(
                    E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
        }

        Bis_pathiId bisPathiId = new Bis_pathiId();
        Bis_pathi bisPathi = new Bis_pathi();
        bisPathiId.setPath_id(path_id);
        bisPathiId.setPath_ver(path_ver);
        bisPathi = bisPathiDao.get(bisPathiId);

        if (bisPathi == null) {
            gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路不存在";
            return new SimpleRtnBeen(
                    E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
        }

        String first_ope_id = bisPathi.getFirst_ope_no();

        if (Util.isSpaceCheck(first_ope_id)) {
            gszMsgBuf = "当前玻璃[" + prd_seq_id + "]工艺线路bis_pathi中维护有误";
            return new SimpleRtnBeen(
                    E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
        }

        if (!(first_ope_id).equals(ret_prd_info.getCr_ope_no_fk())) {
            gszMsgBuf = "要删除的玻璃状态必须在[" + first_ope_id + "]，当前玻璃[" + prd_seq_id + "]位于["
                    + ret_prd_info.getCr_ope_no_fk() + "]，禁止取消！";
            return new SimpleRtnBeen(
                    E_XPUNPACK_CANCEL_PRD_INFO_CR_PROC_INVALIED);
        }
        return new SimpleRtnBeen(ret_prd_info);
    }

    /**
     * Reset ret_prd_in
     *
     * @param wo_id
     * @param mtrl_box_id_fk
     * @return {Ret_prd_in}
     */
    private SimpleRtnBeen resetRetPrdInForCancelUnpack(String wo_id,
                                                       String mtrl_box_id_fk) {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Ret_prd_in ret_prd_in = new Ret_prd_in();

        rtnBeen = retPrdInDao.getRetPrdInByWoAndBox(wo_id, mtrl_box_id_fk);
        if (E_RET_PRD_IN + E_READ_NOT_FOUND == rtnBeen.getlRc()) {
            gszMsgBuf = new NotFoundRtnBeen("boxId:[" + mtrl_box_id_fk
                    + "], WoId:[" + wo_id + "] ", Ret_prd_in.class).toString();
            return new SimpleRtnBeen(rtnBeen.getlRc());
        } else {
            ret_prd_in = (Ret_prd_in) rtnBeen.getObj();
        }

        // Status
        if (PROC_RELS.equals(ret_prd_in.getPpbox_stat())) {
            if (ret_prd_in.getPrd_proc_qty().equals(1)) {
                ret_prd_in.setPpbox_stat(PROC_WFRL);
            }
        } else if (PROC_EMPTY.equals(ret_prd_in.getPpbox_stat())) {
            ret_prd_in.setPpbox_stat(PROC_RELS);
        } else {
            gszMsgBuf = "Mtrl box's status [" + ret_prd_in.getPpbox_stat()
                    + "] is invalied! Must [" + PROC_RELS + "] or ["
                    + PROC_RELS + "]";
            return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
        }
        ret_prd_in.setPrd_proc_qty(ret_prd_in.getPrd_proc_qty() - 1);
        ret_prd_in.setPrd_act_qty(ret_prd_in.getPrd_act_qty() + 1);
        ret_prd_in.setEvt_cate(EVT_CANCEL_UNPACK);
        ret_prd_in.setEvt_usr(inTrx.getEvt_usr());
        retPrdInDao.update(ret_prd_in);

        return new SimpleRtnBeen(ret_prd_in);
    }

    /**
     * Delete ret_prd_indt
     *
     * @param prd_seq_id
     * @return
     */
    private SimpleRtnBeen delRetPrdIndtForCancelUnpack(String prd_seq_id) {
        Ret_prd_indtId ret_prd_indtId = new Ret_prd_indtId();

        ret_prd_indtId.setVdr_prd_seq_id(prd_seq_id);
        ret_prd_indtId.setAct_typ(_NO);
        retPrdIndtDao.deleteByKey(ret_prd_indtId);

        return new SimpleRtnBeen(_NORMAL);
    }

    /**
     * Reset ret_box info
     *
     * @param ret_box_id
     * @param ret_prd_in
     * @return {Ret_box}
     */
    private SimpleRtnBeen resetRetBoxForCancelUnpack(String ret_box_id,
                                                     Ret_prd_in ret_prd_in) {
        Ret_box ret_box = new Ret_box();
        ret_box = retBoxDao.getWithLock(ret_box_id, LockMode.UPGRADE);
        if (null == ret_box) {
            gszMsgBuf = new NotFoundRtnBeen(ret_box_id, Ret_box.class)
                    .toString();
            return new SimpleRtnBeen(E_RET_BOX + E_READ_NOT_FOUND);
        }

        // Status
        if (!PROC_EMPTY.equals(ret_box.getBox_stat())) {
            gszMsgBuf = "Box [" + ret_box.getBox_id() + "] " + "status is ["
                    + ret_box.getBox_stat() + "], " + "must " + PROC_EMPTY
                    + "!";
            return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_STATUS);
        }

        // Set Count
        if (ret_box.getPrd_qty().equals(1)) {
            ret_box = retBoxDao.setBoxEmpt(ret_box);
        } else {
            ret_box.setPrd_qty(ret_box.getPrd_qty() - 1);
        }

        if (ret_box.getPrd_qty().equals(0)) {
            ret_box.setBnk_flg(BANK_OUT);
        }
        retBoxDao.update(ret_box);

        return new SimpleRtnBeen(ret_box);
    }

    /**
     * ret_prd_info ret_prd_info
     *
     * @param ret_prd_info
     * @return
     */
    private SimpleRtnBeen delRetPrdInfoForCancelUnpack(Ret_prd_info ret_prd_info) {
        ret_prd_info.setEvt_timestamp(gEvtTimestamp);
        ret_prd_info.setEvt_time_d(gEvtTimeD);
        ret_prd_info.setEvt_usr(inTrx.getEvt_usr());
        ret_prd_info.setEvt_cate(EVT_CANCEL_UNPACK);
        retPrdInfoDao.delete(ret_prd_info);
        return new SimpleRtnBeen(_NORMAL);
    }

    /**
     * Reset ret_wo
     *
     * @param wo_id_fk
     * @return
     */
    private SimpleRtnBeen resetRetWoForCancelUnpack(String wo_id_fk) {
        Ret_wo ret_wo = new Ret_wo();

        ret_wo = retWoDao.getWithLock(wo_id_fk, LockMode.UPGRADE);
        if (null == ret_wo) {
            gszMsgBuf = new NotFoundRtnBeen(wo_id_fk, Ret_wo.class).toString();
            return new SimpleRtnBeen(E_RET_WO + E_READ_NOT_FOUND);
        }

        ret_wo.setRl_prd_qty(ret_wo.getRl_prd_qty() - 1);
        retWoDao.update(ret_wo);

        return new SimpleRtnBeen(ret_wo);
    }

    /**
     * Delete defect info
     *
     * @param prd_seq_id
     * @return
     */
    private SimpleRtnBeen delDefForCancelUnpack(String prd_seq_id) {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        rtnBeen = retPrdJgeDao.delAllDefByPrdId(prd_seq_id);
        if (_NORMAL != rtnBeen.getlRc()) {
            return rtnBeen;
        }
        return rtnBeen;
    }

    private void setOutTrxForCancelUnpack(String ret_prd_id,
                                          Ret_wo ret_wo, Ret_prd_in ret_prd_in) {
        outTrx.setPrd_seq_id(ret_prd_id);
        outTrx.setEvt_timestamp(gEvtTimestamp.toString());
        outTrx.setEvt_usr(inTrx.getEvt_usr());
        outTrx.setFrom_thickness(ret_wo.getFrom_thickness());
        outTrx.setTo_thickness(ret_wo.getTo_thickness());
        outTrx.setPln_prd_qty(ret_wo.getPln_prd_qty());
        outTrx.setRl_prd_qty(ret_wo.getRl_prd_qty());
        outTrx.setRet_prd_in(ret_prd_in);
    }

    /**
     * 自动创建产品ID，检查RET_PRD_INDT
     */
    private String creatPrd(Ret_wo ret_wo) {
        String prdKey = ret_wo.getCus_id_fk() + ret_wo.getWo_id();
        return retPrdIndtDao.createPrdIdLoop(prdKey);
    }

    /**
     * 新增prd grd info表
     */
    private SimpleRtnBeen addPrdGrdInfoForUnpack(Ret_wo ret_wo, String ret_seq_id) {
        SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
        Integer pnl_std_pnl = 0;
        String prd_seq_grd = "";
        String prd_seq_grd_t = "";
        String prd_seq_grd_c = "";
        Ret_prd_grd_info prd_grd_info = new Ret_prd_grd_info();
        pnl_std_pnl = Integer.valueOf(inTrx.getX_axis_cnt())
                * Integer.valueOf(inTrx.getY_axis_cnt());
        prd_grd_info.setPrd_seq_id_fk(ret_seq_id);
        prd_grd_info.setMdl_id_fk(ret_wo.getMdl_id_fk());
        for (int i = 0; i < pnl_std_pnl; i++) {
            prd_seq_grd = prd_seq_grd + "O";
            prd_seq_grd_t = prd_seq_grd_t + "O";
            prd_seq_grd_c = prd_seq_grd_c + "O";
        }
        prd_grd_info.setPrd_seq_grd(prd_seq_grd);
        prd_grd_info.setPrd_seq_grd_t(prd_seq_grd_t);
        prd_grd_info.setPrd_seq_grd_c(prd_seq_grd_c);
        prd_grd_info.setEvt_usr(inTrx.getEvt_usr());
        prd_grd_info.setEvt_timestamp(gEvtTimestamp);
        prd_grd_info.setPrd_qty(pnl_std_pnl);
        prd_grd_info.setPrd_std_qty(pnl_std_pnl);
        prd_grd_info.setLayot_id_fk(inTrx.getLayot_id());
        prd_grd_info.setX_axis_cnt_fk(Integer.valueOf(inTrx.getX_axis_cnt()));
        prd_grd_info.setY_axis_cnt_fk(Integer.valueOf(inTrx.getY_axis_cnt()));
        prd_grd_info.setCus_ng_qty(0);
        prd_grd_info.setProc_ng_qty(0);
        prd_grd_info.setAct_cus_ng_qty(0);
        prd_grd_info.setAct_proc_ng_qty(0);
        retPrdGrdInfoDao.save(prd_grd_info);
        return rtnBeen;
    }

    /**
     * 删除prd grd info
     */
    private SimpleRtnBeen delRetGrdInfoForCancelUnpack() {
        Ret_prd_grd_info prd_grd_info = new Ret_prd_grd_info();
        prd_grd_info = retPrdGrdInfoDao.get(inTrx.getPrd_seq_id());
        if (prd_grd_info != null) {
            retPrdGrdInfoDao.delete(prd_grd_info);
        }
        return new SimpleRtnBeen(_NORMAL);
    }

    /**
     * 获取RET_CUS_PRD_IN信息
     * 客户订单，必须有客户来料
     * 非客户订单，不能提配客户来料
     */
    private SimpleRtnBeen retCusPrdInCheck(Ret_wo ret_wo) {
        Ret_cus_prd_in ret_cus_prd_in = new Ret_cus_prd_in();
        ret_cus_prd_in = retCusPrdInDao.get(inTrx.getMtrl_box_id());
        if (_YES.equals(ret_wo.getSwh_cnt_flg())) {//客户订单
            if (ret_cus_prd_in == null) {//无客户来料信息则提示报错信息
                gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为客户订单，来料箱号必须为客户来料!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_ID);
            } else {//有客户来料信息，返回来料信息
                return new SimpleRtnBeen(ret_cus_prd_in);
            }
        } else {//非客户订单
            if (ret_cus_prd_in != null) {//有客户来料信息，则返回提示错误信息
                gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为非客户订单，来料箱号不允许为客户来料!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_BOX_ID);
            } else {
                return new SimpleRtnBeen(_NORMAL);
            }
        }
    }

    /**
     * 获取RET_CUS_PRD_INDT信息
     * 客户订单，必须有客户来料
     * 非客户订单，不能提配客户来料
     */
    private SimpleRtnBeen retCusPrdIndtCheck(String prdId, Ret_wo ret_wo) {
        Ret_cus_prd_indt ret_cus_prd_indt = new Ret_cus_prd_indt();
        ret_cus_prd_indt = retCusPrdIndtDao.get(prdId);
        if (_YES.equals(ret_wo.getSwh_cnt_flg())) {//客户订单
            if (ret_cus_prd_indt == null) {//无客户来料信息则提示报错信息
                gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为客户订单，产品ID必须为客户来料!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_PRD_ID);
            } else {//有客户来料信息，返回来料信息
                if (!ret_cus_prd_indt.getMtrl_box_id().equals(inTrx.getMtrl_box_id())) {
                    gszMsgBuf = "来料箱不匹配，产品ID[" + prdId + "]来料箱["
                            + ret_cus_prd_indt.getMtrl_box_id() + "]vs["
                            + inTrx.getMtrl_box_id() + "]!";
                    return new SimpleRtnBeen(E_XPUNPACK_MTRL_BOX_INVALIED);
                } else {
                    return new SimpleRtnBeen(ret_cus_prd_indt);
                }
            }
        } else {//非客户订单
            if (ret_cus_prd_indt != null) {//有客户来料信息，则返回提示错误信息
                gszMsgBuf = "内部订单号 [" + ret_wo.getWo_id() + "]为非客户订单，产品ID不允许为客户来料!";
                return new SimpleRtnBeen(E_XPUNPACK_INVALID_PRD_ID);
            } else {
                return new SimpleRtnBeen(_NORMAL);
            }
        }
    }

    /**
     * Get & check prd_info for cancel unpack
     *
     * @param prd_seq_id
     * @return {Ret_prd_info}
     */
    private SimpleRtnBeen ResetPrdLotInfoForCancelUnpack(String prd_seq_id) {
        Ret_prd_info ret_prd_info = new Ret_prd_info();

        ret_prd_info = retPrdInfoDao.get(prd_seq_id);
        if (null == ret_prd_info) {
            gszMsgBuf = new NotFoundRtnBeen(prd_seq_id, Ret_prd_info.class)
                    .toString();
            return new SimpleRtnBeen(E_RET_PRD_INFO + E_READ_NOT_FOUND);
        }

        // lot_id
        if (Util.isSpaceCheck(ret_prd_info.getLot_id())) {
            return new SimpleRtnBeen(ret_prd_info);
        }

        String sql = "FROM Ret_prd_lot where lot_id = '" + ret_prd_info.getLot_id() + "'";
        List<Ret_prd_lot> lotList = new ArrayList<Ret_prd_lot>();
        lotList = retPrdLotDao.find(sql);
        if (!lotList.isEmpty()) {
            int lotQty = lotList.get(0).getLot_qty();
            lotList.get(0).setLot_qty(lotQty - 1);
            retPrdLotDao.update(lotList.get(0));
        }

        return new SimpleRtnBeen(ret_prd_info);
    }

    private long checkXmtmPrdIndtProc() {
        String woId = inTrx.getWo_id();
        String shtId = inTrx.getPrd_seq_id();

        Ret_wo retWo = retWoDao.get(woId);
        String cusId = retWo.getCus_id_fk();

        boolean isXMTMProd = bisDataDao.checkEdiCusProc("XMTM", cusId);
        if (isXMTMProd) {
            String boxId = inTrx.getBox_id();
            Ret_tm_cus_prd_in tmBox = retTmCusPrdInDao.get(boxId);
            if (tmBox != null) {
                Ret_tm_cus_prd_indt retTmCusPrdindt = retTmCusPrdIndtDao.get(shtId);
                outTrx.setHas_custom_material_flg(retTmCusPrdindt == null ? "N" : "Y");
            }
        } else {
            outTrx.setHas_custom_material_flg("Y");
        }
        outTrx.setOut_control_flg("N");
        if (inTrx.getOut_chk_flg().equals("Y")) {
            Bis_mdl_def bis_mdl_def = bisMdlDefDao.get(retWo.getMdl_id_fk());
            if (!Util.isSpaceCheck(bis_mdl_def.getMdl_param())) {
                List<Bis_data> dataList = new ArrayList<Bis_data>();
                String hql = "FROM Bis_data where data_cate = 'PRDM' and data_id = '" + bis_mdl_def.getMdl_param() + "'";
                dataList = bisDataDao.find(hql);
                if (!dataList.isEmpty()) {
                    for (Bis_data bis_data : dataList) {
                        String data_ext = bis_data.getData_ext();
                        String ext_1 = bis_data.getExt_1();
                        String[] sub = data_ext.split(",");
                        String[] chr = ext_1.split(",");
                        String has_flg = "N";
                        if (shtId.length() < Integer.valueOf(sub[1])) {
                            continue;
                        }
                        for (int i = 0; i < chr.length; i++) {
                            if (shtId.substring(Integer.valueOf(sub[0]), Integer.valueOf(sub[1])).equals(chr[i])) {
                                has_flg = "Y";
                                break;
                            }
                        }
                        if (has_flg.equals("N")) {
                            outTrx.setOut_control_flg("Y");
                            break;
                        }
                    }
                }
            }
        }
        outTrx.setRtn_code(RETURN_CODE_OK);
        outTrx.setRtn_mesg(RETURN_MESG_OK);
        return 0;
    }


}
